/*
 * @Author: hanyuanjiao
 * @Date: 2025-07-21 06:52:28
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2025-08-19 14:27:32
 * @Description: 请填写简介
 */
#include "simu8051.h"
#include <string.h>
#include <stdio.h>
#include "tools.h"
#include "mem.h"

simu8051_t simu;

//将所有指令信息做成一个常量表
static const instr_info_t instr_table[256] = {
    [0x00] = {1, 1, OTYPE_NONE, OTYPE_NONE, do_nop, "NOP", "", ""},                               // NOP
    [0x01] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_ajmp, "AJMP", "addr11", ""},                       // AJMP addr11
    [0x02] = {3, 2, OTYPE_NONE, OTYPE_NONE, do_ljmp, "LJMP", "addr16", ""},                       // LJMP addr16
    [0x03] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_rr, "RR", "A", ""},                                 // RR A
    [0x04] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_inc, "INC", "A", ""},                               // inc A
    [0x05] = {2, 1, OTYPE_DIRECT, OTYPE_NONE, do_inc, "INC", "direct", ""},                       // inc direct
    [0x06] = {1, 1, OTYPE_INDIRECT_R0_1, OTYPE_NONE, do_inc, "INC", "@R0", ""},                   // inc @R0
    [0x07] = {1, 1, OTYPE_INDIRECT_R0_1, OTYPE_NONE, do_inc, "INC", "@R1", ""},                   // inc @R1
    [0x08] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_inc, "INC", "R0", ""},                               // inc R0
    [0x09] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_inc, "INC", "R1", ""},                               // inc R1
    [0x0a] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_inc, "INC", "R2", ""},                               // inc R2
    [0x0b] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_inc, "INC", "R3", ""},                               // inc R3
    [0x0c] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_inc, "INC", "R4", ""},                               // inc R4
    [0x0d] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_inc, "INC", "R5", ""},                               // inc R5
    [0x0e] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_inc, "INC", "R6", ""},                               // inc R6
    [0x0f] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_inc, "INC", "R7", ""},                               // inc R7
    [0x10] = {3, 2, OTYPE_BIT, OTYPE_IMM8, do_jb, "JBC", "bit", "rel"},                           // jbc bit,rel
    [0x11] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_acall, "ACALL", "addr11", ""},                     // acall addr11
    [0x12] = {3, 2, OTYPE_NONE, OTYPE_NONE, do_lcall, "LCALL", "addr16", ""},                     // lcall addr16
    [0x13] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_rr, "RRC", "A", ""},                                // RRC A
    [0x14] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_dec, "DEC", "A", ""},                               // dec A
    [0x15] = {2, 1, OTYPE_DIRECT, OTYPE_NONE, do_dec, "DEC", "direct", ""},                       // dec direct
    [0x16] = {1, 1, OTYPE_INDIRECT_R0_1, OTYPE_NONE, do_dec, "DEC", "@R0", ""},                   // dec @R0
    [0x17] = {1, 1, OTYPE_INDIRECT_R0_1, OTYPE_NONE, do_dec, "DEC", "@R1", ""},                   // dec @R1
    [0x18] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_dec, "DEC", "R0", ""},                               // dec R0
    [0x19] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_dec, "DEC", "R1", ""},                               // dec R1
    [0x1a] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_dec, "DEC", "R2", ""},                               // dec R2
    [0x1b] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_dec, "DEC", "R3", ""},                               // dec R3
    [0x1c] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_dec, "DEC", "R4", ""},                               // dec R4
    [0x1d] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_dec, "DEC", "R5", ""},                               // dec R5
    [0x1e] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_dec, "DEC", "R6", ""},                               // dec R6
    [0x1f] = {1, 1, OTYPE_Rn, OTYPE_NONE, do_dec, "DEC", "R7", ""},                               // dec R7
    [0x20] = {3, 2, OTYPE_BIT, OTYPE_IMM8, do_jb, "JB", "bit", "rel"},                            // jb bit,rel
    [0x21] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_ajmp, "AJMP", "addr11", ""},                       // AJMP addr11
    [0x22] = {1, 2, OTYPE_NONE, OTYPE_NONE, do_ret, "RET", "", ""},                               // ret
    [0x23] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_rl, "RL", "A", ""},                                 // RL A
    [0x24] = {2, 1, OTYPE_ACC, OTYPE_IMM8, do_add, "ADD", "A", "#imm8"},                          // add A,#imm8
    [0x25] = {2, 1, OTYPE_ACC, OTYPE_DIRECT, do_add, "ADD", "A", "direct"},                       // add A,direct
    [0x26] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_add, "A", "@R0"},                          // add A,@R0
    [0x27] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_add, "A", "@R1"},                          // add A,@R1
    [0x28] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "ADD", "A", "R0"},                               // add A,R0
    [0x29] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "ADD", "A", "R1"},                               // add A,R1
    [0x2a] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "ADD", "A", "R2"},                               // add A,R2
    [0x2b] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "ADD", "A", "R3"},                               // add A,R3
    [0x2c] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "ADD", "A", "R4"},                               // add A,R4
    [0x2d] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "ADD", "A", "R5"},                               // add A,R5
    [0x2e] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "ADD", "A", "R6"},                               // add A,R6
    [0x2f] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "ADD", "A", "R7"},                               // add A,R7
    [0x30] = {3, 2, OTYPE_BIT, OTYPE_IMM8, do_jb, "JNB", "bit", "rel"},                           // jnb bit,rel
    [0x31] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_acall, "ACALL", "addr11", ""},                     // acall addr11
    [0x32] = {1, 2, OTYPE_NONE, OTYPE_NONE, do_reti, "RETI", "", ""},                             // reti
    [0x33] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_rl, "RLC", "A", ""},                                // RLC A
    [0x34] = {2, 1, OTYPE_ACC, OTYPE_IMM8, do_add, "addc", "A", "#imm8"},                         // addc A,#imm8
    [0x35] = {2, 1, OTYPE_ACC, OTYPE_DIRECT, do_add, "addc", "A", "direct"},                      // addc A,direct
    [0x36] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_add, "A", "@R0"},                          // addc A,@R0
    [0x37] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_add, "A", "@R1"},                          // addc A,@R1
    [0x38] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "addc", "A", "R0"},                              // addc A,R0
    [0x39] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "addc", "A", "R1"},                              // addc A,R1
    [0x3a] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "addc", "A", "R2"},                              // addc A,R2
    [0x3b] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "addc", "A", "R3"},                              // addc A,R3
    [0x3c] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "addc", "A", "R4"},                              // addc A,R4
    [0x3d] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "addc", "A", "R5"},                              // addc A,R5
    [0x3e] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "addc", "A", "R6"},                              // addc A,R6
    [0x3f] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_add, "addc", "A", "R7"},                              // addc A,R7
    [0x40] = {2, 2, OTYPE_IMM8, OTYPE_NONE, do_jc, "JC", "rel", ""},                              // JC rel
    [0x41] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_ajmp, "AJMP", "addr11", ""},                       // AJMP addr11
    [0x42] = {2, 1, OTYPE_DIRECT, OTYPE_ACC, do_orl, "ORL", "direct", "A"},                       // orl direct,A
    [0x43] = {3, 2, OTYPE_DIRECT, OTYPE_IMM8, do_orl, "ORL", "direct", "#imm8"},                  // orl direct,#imm8
    [0x44] = {2, 1, OTYPE_ACC, OTYPE_IMM8, do_orl, "ORL", "A", "#imm8"},                          // orl A,#imm8
    [0x45] = {2, 1, OTYPE_ACC, OTYPE_DIRECT, do_orl, "ORL", "A", "direct"},                       // orl A,direct
    [0x46] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_orl, "ORL", "A", "@R0"},                   // orl A,@R0
    [0x47] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_orl, "ORL", "A", "@R1"},                   // orl A,@R1
    [0x48] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_orl, "ORL", "A", "R0"},                               // orl A,R0
    [0x49] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_orl, "ORL", "A", "R1"},                               // orl A,R1
    [0x4a] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_orl, "ORL", "A", "R2"},                               // orl A,R2
    [0x4b] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_orl, "ORL", "A", "R3"},                               // orl A,R3
    [0x4c] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_orl, "ORL", "A", "R4"},                               // orl A,R4
    [0x4d] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_orl, "ORL", "A", "R5"},                               // orl A,R5
    [0x4e] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_orl, "ORL", "A", "R6"},                               // orl A,R6
    [0x4f] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_orl, "ORL", "A", "R7"},                               // orl A,R7
    [0x50] = {2, 2, OTYPE_IMM8, OTYPE_NONE, do_jc, "JNC", "rel", ""},                             // JNC rel
    [0x51] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_acall, "ACALL", "addr11", ""},                     // acall addr11
    [0x52] = {2, 1, OTYPE_DIRECT, OTYPE_ACC, do_anl, "ANL", "direct", "A"},                       // anl direct,A
    [0x53] = {3, 2, OTYPE_DIRECT, OTYPE_IMM8, do_anl, "ANL", "direct", "#imm8"},                  // anl direct,#imm8
    [0x54] = {2, 1, OTYPE_ACC, OTYPE_IMM8, do_anl, "ANL", "A", "#imm8"},                          // anl A,#imm8
    [0x55] = {2, 1, OTYPE_ACC, OTYPE_DIRECT, do_anl, "ANL", "A", "direct"},                       // anl A,direct
    [0x56] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_anl, "ANL", "A", "@R0"},                   // anl A,@R0
    [0x57] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_anl, "ANL", "A", "@R1"},                   // anl A,@R1
    [0x58] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_anl, "ANL", "A", "R0"},                               // anl A,R0
    [0x59] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_anl, "ANL", "A", "R1"},                               // anl A,R1
    [0x5a] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_anl, "ANL", "A", "R2"},                               // anl A,R2
    [0x5b] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_anl, "ANL", "A", "R3"},                               // anl A,R3
    [0x5c] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_anl, "ANL", "A", "R4"},                               // anl A,R4
    [0x5d] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_anl, "ANL", "A", "R5"},                               // anl A,R5
    [0x5e] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_anl, "ANL", "A", "R6"},                               // anl A,R6
    [0x5f] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_anl, "ANL", "A", "R7"},                               // anl A,R7
    [0x60] = {2, 2, OTYPE_IMM8, OTYPE_NONE, do_jz, "JZ", "rel", ""},                              // JZ rel
    [0x61] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_ajmp, "AJMP", "addr11", ""},                       // AJMP addr11
    [0x62] = {2, 1, OTYPE_DIRECT, OTYPE_ACC, do_xrl, "XRL", "direct", "A"},                       // xrl direct,A
    [0x63] = {3, 2, OTYPE_DIRECT, OTYPE_IMM8, do_xrl, "XRL", "direct", "#imm8"},                  // xrl direct,#imm8
    [0x64] = {2, 1, OTYPE_ACC, OTYPE_IMM8, do_xrl, "XRL", "A", "#imm8"},                          // xrl A,#imm8
    [0x65] = {2, 1, OTYPE_ACC, OTYPE_DIRECT, do_xrl, "XRL", "A", "direct"},                       // xrl A,direct
    [0x66] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_xrl, "XRL", "A", "@R0"},                   // xrl A,@R0
    [0x67] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_xrl, "XRL", "A", "@R1"},                   // xrl A,@R1
    [0x68] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xrl, "XRL", "A", "R0"},                               // xrl A,R0
    [0x69] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xrl, "XRL", "A", "R1"},                               // xrl A,R1
    [0x6a] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xrl, "XRL", "A", "R2"},                               // xrl A,R2
    [0x6b] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xrl, "XRL", "A", "R3"},                               // xrl A,R3
    [0x6c] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xrl, "XRL", "A", "R4"},                               // xrl A,R4
    [0x6d] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xrl, "XRL", "A", "R5"},                               // xrl A,R5
    [0x6e] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xrl, "XRL", "A", "R6"},                               // xrl A,R6
    [0x6f] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xrl, "XRL", "A", "R7"},                               // xrl A,R7
    [0x70] = {2, 2, OTYPE_IMM8, OTYPE_NONE, do_jz, "JNZ", "rel", ""},                             // JNZ rel
    [0x71] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_acall, "ACALL", "addr11", ""},                     // acall addr11
    [0x72] = {2, 2, OTYPE_C, OTYPE_BIT, do_orl, "ORL", "C", "bit"},                               // orl c,bit
    [0x73] = {1, 2, OTYPE_INDIRECT_ACC_DPTR, OTYPE_NONE, do_jmp_a_dptr, "JMP", "@A+DPTR", ""},    // JMP @A+DPTR
    [0x74] = {2, 1, OTYPE_ACC, OTYPE_IMM8, do_mov, "MOV", "A", "#imm8"},                          // mov A,#data
    [0x75] = {3, 2, OTYPE_DIRECT, OTYPE_IMM8, do_mov, "MOV", "direct", "#imm8"},                  // mov direct,#data
    [0x76] = {2, 1, OTYPE_INDIRECT_R0_1, OTYPE_IMM8, do_mov, "MOV", "@R0", "#imm8"},              // mov @R0,#imm8
    [0x77] = {2, 1, OTYPE_INDIRECT_R0_1, OTYPE_IMM8, do_mov, "MOV", "@R1", "#imm8"},              // mov @R1,#imm8
    [0x78] = {2, 1, OTYPE_Rn, OTYPE_IMM8, do_mov, "MOV", "R0", "#imm8"},                          // mov R0,#data
    [0x79] = {2, 1, OTYPE_Rn, OTYPE_IMM8, do_mov, "MOV", "R1", "#imm8"},                          // mov R1,#data
    [0x7a] = {2, 1, OTYPE_Rn, OTYPE_IMM8, do_mov, "MOV", "R2", "#imm8"},                          // mov R2,#data
    [0x7b] = {2, 1, OTYPE_Rn, OTYPE_IMM8, do_mov, "MOV", "R3", "#imm8"},                          // mov R3,#data
    [0x7c] = {2, 1, OTYPE_Rn, OTYPE_IMM8, do_mov, "MOV", "R4", "#imm8"},                          // mov R4,#data
    [0x7d] = {2, 1, OTYPE_Rn, OTYPE_IMM8, do_mov, "MOV", "R5", "#imm8"},                          // mov R5,#data
    [0x7e] = {2, 1, OTYPE_Rn, OTYPE_IMM8, do_mov, "MOV", "R6", "#imm8"},                          // mov R6,#data
    [0x7f] = {2, 1, OTYPE_Rn, OTYPE_IMM8, do_mov, "MOV", "R7", "#imm8"},                          // mov R7,#data
    [0x80] = {2, 2, OTYPE_IMM8, OTYPE_NONE, do_sjmp, "SJMP", "rel", ""},                          // sjmp
    [0x81] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_ajmp, "AJMP", "addr11", ""},                       // AJMP addr11
    [0x82] = {2, 2, OTYPE_C, OTYPE_BIT, do_anl, "ANL", "C", "bit"},                               // anl c,bit
    [0x83] = {1, 2, OTYPE_ACC, OTYPE_INDIRECT_ACC_PC, do_movc, "movC", "A", "@A+PC"},             // movc A,@A+PC
    [0x84] = {1, 4, OTYPE_ACC, OTYPE_B, do_div, "div", "AB", ""},                                 // div ab
    // mov direct0,direct0,芯片是op0->op1,这里需要特殊处理
    [0x85] = {3, 2, OTYPE_DIRECT, OTYPE_DIRECT, do_mov, "MOV", "direct", "direct"},
    [0x86] = {2, 2, OTYPE_DIRECT, OTYPE_INDIRECT_R0_1, do_mov, "MOV", "direct", "@R0"},    // mov direct,@R0
    [0x87] = {2, 2, OTYPE_DIRECT, OTYPE_INDIRECT_R0_1, do_mov, "MOV", "direct", "@R1"},    // mov direct,@R1
    [0x88] = {2, 2, OTYPE_DIRECT, OTYPE_Rn, do_mov, "MOV", "direct", "R0"},                // mov direct,R0
    [0x89] = {2, 2, OTYPE_DIRECT, OTYPE_Rn, do_mov, "MOV", "direct", "R1"},                // mov direct,R1
    [0x8a] = {2, 2, OTYPE_DIRECT, OTYPE_Rn, do_mov, "MOV", "direct", "R2"},                // mov direct,R2
    [0x8b] = {2, 2, OTYPE_DIRECT, OTYPE_Rn, do_mov, "MOV", "direct", "R3"},                // mov direct,R3
    [0x8c] = {2, 2, OTYPE_DIRECT, OTYPE_Rn, do_mov, "MOV", "direct", "R4"},                // mov direct,R4
    [0x8d] = {2, 2, OTYPE_DIRECT, OTYPE_Rn, do_mov, "MOV", "direct", "R5"},                // mov direct,R5
    [0x8e] = {2, 2, OTYPE_DIRECT, OTYPE_Rn, do_mov, "MOV", "direct", "R6"},                // mov direct,R6
    [0x8f] = {2, 2, OTYPE_DIRECT, OTYPE_Rn, do_mov, "MOV", "direct", "R7"},                // mov direct,R7
    [0x90] = {3, 2, OTYPE_DPTR, OTYPE_IMM16, do_mov, "MOV", "DPTR", "#imm16"},             // move direct,#imm16
    [0x91] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_acall, "ACALL", "addr11", ""},              // acall addr11
    [0x92] = {2, 2, OTYPE_BIT, OTYPE_C, do_mov, "MOV", "bit", "C"},                        // mov bit,C
    [0x93] = {1, 2, OTYPE_ACC, OTYPE_INDIRECT_ACC_DPTR, do_movc, "movC", "A", "@A+DPTR"},
    [0x94] = {2, 1, OTYPE_ACC, OTYPE_IMM8, do_subb, "subb", "A", "#imm8"},                    // subb A,#imm8
    [0x95] = {2, 1, OTYPE_ACC, OTYPE_DIRECT, do_subb, "subb", "A", "direct"},                 // subb A,direct
    [0x96] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_subb, "subb", "A", "@R0"},             // subb A,@R0
    [0x97] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_subb, "subb", "A", "@R1"},             // subb A,@R1
    [0x98] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_subb, "subb", "A", "R0"},                         // subb A,R0
    [0x99] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_subb, "subb", "A", "R1"},                         // subb A,R1
    [0x9a] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_subb, "subb", "A", "R2"},                         // subb A,R2
    [0x9b] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_subb, "subb", "A", "R3"},                         // subb A,R3
    [0x9c] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_subb, "subb", "A", "R4"},                         // subb A,R4
    [0x9d] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_subb, "subb", "A", "R5"},                         // subb A,R5
    [0x9e] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_subb, "subb", "A", "R6"},                         // subb A,R6
    [0x9f] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_subb, "subb", "A", "R7"},                         // subb A,R7
    [0xa0] = {2, 2, OTYPE_C, OTYPE_INV_BIT, do_orl, "ORL", "C", "/bit"},                      // orl c,/bit
    [0xa1] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_ajmp, "AJMP", "addr11", ""},                   // AJMP addr11
    [0xa2] = {2, 1, OTYPE_C, OTYPE_BIT, do_mov, "MOV", "C", "bit"},                           // mov C,bit
    [0xa3] = {1, 2, OTYPE_DPTR, OTYPE_NONE, do_inc, "INC", "dptr", ""},                       // inc dptr
    [0xa4] = {1, 4, OTYPE_ACC, OTYPE_B, do_mul, "MUL", "AB", ""},                             // mul ab
    [0xa6] = {2, 2, OTYPE_INDIRECT_R0_1, OTYPE_DIRECT, do_mov, "MOV", "@R0", "direct"},       // mov @R0,direct
    [0xa7] = {2, 2, OTYPE_INDIRECT_R0_1, OTYPE_DIRECT, do_mov, "MOV", "@R1", "direct"},       // mov @R1,direct
    [0xa8] = {2, 2, OTYPE_Rn, OTYPE_DIRECT, do_mov, "MOV", "R0", "direct"},                   // mov R0,direct
    [0xa9] = {2, 2, OTYPE_Rn, OTYPE_DIRECT, do_mov, "MOV", "R1", "direct"},                   // mov R1,direct
    [0xaa] = {2, 2, OTYPE_Rn, OTYPE_DIRECT, do_mov, "MOV", "R2", "direct"},                   // mov R2,direct
    [0xab] = {2, 2, OTYPE_Rn, OTYPE_DIRECT, do_mov, "MOV", "R3", "direct"},                   // mov R3,direct
    [0xac] = {2, 2, OTYPE_Rn, OTYPE_DIRECT, do_mov, "MOV", "R4", "direct"},                   // mov R4,direct
    [0xad] = {2, 2, OTYPE_Rn, OTYPE_DIRECT, do_mov, "MOV", "R5", "direct"},                   // mov R5,direct
    [0xae] = {2, 2, OTYPE_Rn, OTYPE_DIRECT, do_mov, "MOV", "R6", "direct"},                   // mov R6,direct
    [0xaf] = {2, 2, OTYPE_Rn, OTYPE_DIRECT, do_mov, "MOV", "R7", "direct"},                   // mov R7,direct
    [0xb0] = {2, 2, OTYPE_C, OTYPE_INV_BIT, do_anl, "ANL", "C", "/bit"},                      // anl c,/bit
    [0xb1] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_acall, "ACALL", "addr11", ""},                 // acall addr11
    [0xb2] = {2, 1, OTYPE_BIT, OTYPE_NONE, do_cpl, "CPL", "BIT", ""},                         // cpl bit
    [0xb3] = {1, 1, OTYPE_C, OTYPE_NONE, do_cpl, "CPL", "C", ""},                             // cpl C
    [0xb4] = {3, 2, OTYPE_ACC, OTYPE_IMM8, do_cjne, "CJNE", "A,#data", "rel"},                // cjne A,#data,rel
    [0xb5] = {3, 2, OTYPE_ACC, OTYPE_DIRECT, do_cjne, "CJNE", "A,direct", "rel"},             // cjne A,direct,rel
    [0xb6] = {3, 2, OTYPE_INDIRECT_R0_1, OTYPE_IMM8, do_cjne, "CJNE", "@R0,#data", "rel"},    // cjne @Ri,#data,rel
    [0xb7] = {3, 2, OTYPE_INDIRECT_R0_1, OTYPE_IMM8, do_cjne, "CJNE", "@R1,#data", "rel"},    // cjne @Ri,#data,rel
    [0xb8] = {3, 2, OTYPE_Rn, OTYPE_IMM8, do_cjne, "CJNE", "R0,#data", "rel"},                // cjne R0,#data,rel
    [0xb9] = {3, 2, OTYPE_Rn, OTYPE_IMM8, do_cjne, "CJNE", "R1,#data", "rel"},                // cjne R0,#data,rel
    [0xba] = {3, 2, OTYPE_Rn, OTYPE_IMM8, do_cjne, "CJNE", "R2,#data", "rel"},                // cjne R0,#data,rel
    [0xbb] = {3, 2, OTYPE_Rn, OTYPE_IMM8, do_cjne, "CJNE", "R3,#data", "rel"},                // cjne R0,#data,rel
    [0xbc] = {3, 2, OTYPE_Rn, OTYPE_IMM8, do_cjne, "CJNE", "R4,#data", "rel"},                // cjne R0,#data,rel
    [0xbd] = {3, 2, OTYPE_Rn, OTYPE_IMM8, do_cjne, "CJNE", "R5,#data", "rel"},                // cjne R0,#data,rel
    [0xbe] = {3, 2, OTYPE_Rn, OTYPE_IMM8, do_cjne, "CJNE", "R6,#data", "rel"},                // cjne R0,#data,rel
    [0xbf] = {3, 2, OTYPE_Rn, OTYPE_IMM8, do_cjne, "CJNE", "R7,#data", "rel"},                // cjne R0,#data,rel
    [0xc0] = {2, 2, OTYPE_DIRECT, OTYPE_NONE, do_push, "push", "direct", ""},                 // push direct
    [0xc1] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_ajmp, "AJMP", "addr11", ""},                   // AJMP addr11
    [0xc2] = {2, 1, OTYPE_BIT, OTYPE_NONE, do_clr, "CLR", "bit", ""},                         // clr bit
    [0xc3] = {1, 1, OTYPE_C, OTYPE_NONE, do_clr, "CLR", "C", ""},                             // CLR C
    [0xc4] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_swap, "swap", "A", ""},                         // swap A
    [0xc5] = {2, 1, OTYPE_ACC, OTYPE_DIRECT, do_xch, "xch", "A", "direct"},                   // xch A,direct
    [0xc6] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_xch, "xch", "A", "@R0"},               // xch A,@R0
    [0xc7] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_xch, "xch", "A", "@R1"},               // xch A,@R1
    [0xc8] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xch, "xch", "A", "R0"},                           // xch A,R0
    [0xc9] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xch, "xch", "A", "R1"},                           // xch A,R1
    [0xca] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xch, "xch", "A", "R2"},                           // xch A,R2
    [0xcb] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xch, "xch", "A", "R3"},                           // xch A,R3
    [0xcc] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xch, "xch", "A", "R4"},                           // xch A,R4
    [0xcd] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xch, "xch", "A", "R5"},                           // xch A,R5
    [0xce] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xch, "xch", "A", "R6"},                           // xch A,R6
    [0xcf] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_xch, "xch", "A", "R7"},                           // xch A,R7
    [0xd0] = {2, 2, OTYPE_DIRECT, OTYPE_NONE, do_pop, "pop", "direct", ""},                   // pop direct
    [0xd1] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_acall, "ACALL", "addr11", ""},                 // acall addr11
    [0xd2] = {2, 1, OTYPE_BIT, OTYPE_NONE, do_setb, "SETB", "bit", ""},                       // SETB bit
    [0xd3] = {1, 1, OTYPE_C, OTYPE_NONE, do_setb, "SETB", "C", ""},                           // SETB C
    [0xd4] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_da, "DA", "A", ""},                             // DA A
    [0xd5] = {3, 2, OTYPE_DIRECT, OTYPE_IMM8, do_djnz, "djnz", "direct", "rel"},              // djnz direct,rel
    [0xd6] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_xch, "xchd", "A", "@R0"},              // xchd A,@R0
    [0xd7] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_xch, "xchd", "A", "@R1"},              // xchd A,@R1
    [0xd8] = {2, 2, OTYPE_Rn, OTYPE_IMM8, do_djnz, "djnz", "R0", "rel"},                      // djnz R0,rel
    [0xd9] = {2, 2, OTYPE_Rn, OTYPE_IMM8, do_djnz, "djnz", "R1", "rel"},                      // djnz R1,rel
    [0xda] = {2, 2, OTYPE_Rn, OTYPE_IMM8, do_djnz, "djnz", "R2", "rel"},                      // djnz R2,rel
    [0xdb] = {2, 2, OTYPE_Rn, OTYPE_IMM8, do_djnz, "djnz", "R3", "rel"},                      // djnz R3,rel
    [0xdc] = {2, 2, OTYPE_Rn, OTYPE_IMM8, do_djnz, "djnz", "R4", "rel"},                      // djnz R4,rel
    [0xdd] = {2, 2, OTYPE_Rn, OTYPE_IMM8, do_djnz, "djnz", "R5", "rel"},                      // djnz R5,rel
    [0xde] = {2, 2, OTYPE_Rn, OTYPE_IMM8, do_djnz, "djnz", "R6", "rel"},                      // djnz R6,rel
    [0xdf] = {2, 2, OTYPE_Rn, OTYPE_IMM8, do_djnz, "djnz", "R7", "rel"},                      // djnz R7,rel
    [0xe0] = {1, 2, OTYPE_ACC, OTYPE_INDIRECT_DPTR, do_movx, "movx", "A", "@DPTR"},           // movx A,@DPTR
    [0xe1] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_ajmp, "AJMP", "addr11", ""},                   // AJMP addr11
    [0xe2] = {1, 2, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_movx, "movx", "A", "@R0"},             // movx A,@R0
    [0xe3] = {1, 2, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_movx, "movx", "A", "@R1"},             // movx A,@R1
    [0xe4] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_clr, "CLR", "A", ""},                           // CLR A
    [0xe5] = {2, 1, OTYPE_ACC, OTYPE_DIRECT, do_mov, "MOV", "A", "direct"},                   // mov a,direct
    [0xe6] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_mov, "MOV", "A", "@R0"},               // mov A,@R0
    [0xe7] = {1, 1, OTYPE_ACC, OTYPE_INDIRECT_R0_1, do_mov, "MOV", "A", "@R1"},               // mov A,@R1
    [0xe8] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_mov, "MOV", "A", "R0"},                           // mov A,R0
    [0xe9] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_mov, "MOV", "A", "R1"},                           // mov A,R1
    [0xea] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_mov, "MOV", "A", "R2"},                           // mov A,R2
    [0xeb] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_mov, "MOV", "A", "R3"},                           // mov A,R3
    [0xec] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_mov, "MOV", "A", "R4"},                           // mov A,R4
    [0xed] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_mov, "MOV", "A", "R5"},                           // mov A,R5
    [0xee] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_mov, "MOV", "A", "R6"},                           // mov A,R6
    [0xef] = {1, 1, OTYPE_ACC, OTYPE_Rn, do_mov, "MOV", "A", "R7"},                           // mov A,R7
    [0xf0] = {1, 2, OTYPE_INDIRECT_DPTR, OTYPE_ACC, do_movx, "movx", "@DPTR", "A"},           // movx @DPTR,A
    [0xf1] = {2, 2, OTYPE_NONE, OTYPE_NONE, do_acall, "ACALL", "addr11", ""},                 // acall addr11
    [0xf2] = {1, 2, OTYPE_INDIRECT_R0_1, OTYPE_ACC, do_movx, "movx", "@R0", "A"},             // movx @R0,A
    [0xf3] = {1, 2, OTYPE_INDIRECT_R0_1, OTYPE_ACC, do_movx, "movx", "@R1", "A"},             // movx @R1,A
    [0xf4] = {1, 1, OTYPE_ACC, OTYPE_NONE, do_cpl, "cpl", "A", ""},                           // cpl A
    [0xf5] = {2, 1, OTYPE_DIRECT, OTYPE_ACC, do_mov, "MOV", "direct", "A"},                   // mov direct,A
    [0xf6] = {1, 1, OTYPE_INDIRECT_R0_1, OTYPE_ACC, do_mov, "MOV", "@R0", "A"},               // mov @R0,A
    [0xf7] = {1, 1, OTYPE_INDIRECT_R0_1, OTYPE_ACC, do_mov, "MOV", "@R1", "A"},               // mov @R1,A
    [0xf8] = {1, 1, OTYPE_Rn, OTYPE_ACC, do_mov, "MOV", "R0", "A"},                           // mov R0,A
    [0xf9] = {1, 1, OTYPE_Rn, OTYPE_ACC, do_mov, "MOV", "R1", "A"},                           // mov R1,A
    [0xfa] = {1, 1, OTYPE_Rn, OTYPE_ACC, do_mov, "MOV", "R2", "A"},                           // mov R2,A
    [0xfb] = {1, 1, OTYPE_Rn, OTYPE_ACC, do_mov, "MOV", "R3", "A"},                           // mov R3,A
    [0xfc] = {1, 1, OTYPE_Rn, OTYPE_ACC, do_mov, "MOV", "R4", "A"},                           // mov R4,A
    [0xfd] = {1, 1, OTYPE_Rn, OTYPE_ACC, do_mov, "MOV", "R5", "A"},                           // mov R5,A
    [0xfe] = {1, 1, OTYPE_Rn, OTYPE_ACC, do_mov, "MOV", "R6", "A"},                           // mov R6,A
    [0xff] = {1, 1, OTYPE_Rn, OTYPE_ACC, do_mov, "MOV", "R7", "A"},                           // mov R7,A
};

void simu8051_reset(void)
{
    simu.pc     = 0;
    simu.cycles = 0;
    simu.in_int = 0;
    memset(simu.mem.iram, 0, MEM_IRAM_SIZE);
    memset(simu.mem.sfr, 0, MEM_SFR_SIZE);
    memset(simu.mem.xram, 0, MEM_XRAM_SIZE);
    simu8051_write(MEM_TYPE_SFR, SFR_SP, 0x07);
    /*
    simu8051_write(MEM_TYPE_SFR, SFR_SP, 0x32);
    simu8051_write(MEM_TYPE_IRAM, 0x30, 0x20);
    simu8051_write(MEM_TYPE_IRAM, 0x31, 0x23);
    simu8051_write(MEM_TYPE_IRAM, 0x32, 0x01);
    */
}

void simu8051_init(void)
{
    simu.mem.code = (uint8_t *)0;
    simu8051_reset();
}

void simu8051_load(uint8_t *code)
{
    simu.mem.code = code;
}

uint16_t simu8051_pc(void)
{
    return simu.pc;
}
uint8_t simu8051_sp(void)
{
    return simu8051_read(MEM_TYPE_SFR, SFR_SP);
}
uint32_t simu8051_cycle(void)
{
    return simu.cycles;
}

void simu8051_fetch_instr(instr_t *instr)
{
    instr->opcode = simu.mem.code[simu.pc];
    instr->info   = instr_table + instr->opcode;
    instr->op0    = simu.mem.code[simu.pc + 1];
    instr->op1    = simu.mem.code[simu.pc + 2];
}
/**
 * @description: 更新psw的p标志位
 * @return {*}
 */
static void update_psw_p()
{
    uint8_t v = simu8051_read(MEM_TYPE_SFR, SFR_ACC);
#if 0
    int     count = 0;
    for (int i = 0; i < 8; i++)
    {
        count += ((v >> i) & 0x01);
    }
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_P, count & 0x1);
#else
    // 1100 0111  ---5 ==>1
    // 1100 ^ 0111 = 1011
    // 10 ^ 11 = 01
    // 0 ^ 1=1
    v = (v >> 4) ^ (v & 0x0f);
    v = (v >> 2) ^ (v & 0x03);
    v = (v >> 1) ^ (v & 0x01);
    simu8051_write(MEM_TYPE_BIT, SFR_PSW_P, v);
#endif
}
static void update_timer(int cycles)
{
    uint8_t    tmod = simu8051_read(MEM_TYPE_SFR, SFR_TMOD);
    uint8_t    tr0  = simu8051_read(MEM_TYPE_BIT, SFR_TCON_TR0);
    static int count;
    if (tr0)
    {
        // M10M00 select the timer working mode
        // 00: mode0: 8-bit timer/counter(TH0) with 5bit prescaler(TL0)
        // 01: mode1: 16-bit timer/counter
        // 10: mode2: 8bit auto-reload timer/counter(TL0). reloaded from TH0 at overflow
        // 11: mode3: TL0 is an 8bit timer/counter
        switch (tmod & 3)
        {
        case 0x0:
            break;
        case 0x1:
            count = simu8051_read(MEM_TYPE_SFR, SFR_TH0) << 8 | simu8051_read(MEM_TYPE_SFR, SFR_TL0);
            count += cycles;
            if (count >= 0x10000)
            {
                simu8051_write(MEM_TYPE_BIT, SFR_TCON_TF0, 1);
                count = 0;
            }
            simu8051_write(MEM_TYPE_SFR, SFR_TH0, count >> 8);
            simu8051_write(MEM_TYPE_SFR, SFR_TL0, count & 0xff);
            break;
        case 0x2:
            break;
        case 0x3:
            break;
        }
    }
}
static void enter_interrupt(uint16_t entry)
{
    simu.in_int = 1;
    uint8_t sp  = simu8051_read(MEM_TYPE_IRAM, SFR_SP);
    simu8051_write(MEM_TYPE_IRAM, ++sp, simu.pc & 0xff);
    simu8051_write(MEM_TYPE_IRAM, ++sp, simu.pc >> 8);
    simu8051_write(MEM_TYPE_IRAM, SFR_SP, sp);
    simu.pc     = entry;
}
static void process_interrupt(void)
{
    // only timer0
    uint8_t IE  = simu8051_read(MEM_TYPE_SFR, SFR_IE);
    uint8_t EA  = IE & 0x80;
    uint8_t ET0 = IE & (1 << 1);
    if (!EA)
    {
        return;
    }
    if (simu.in_int)
    {
        return;
    }
    if (ET0)
    {
        uint8_t tf0 = simu8051_read(MEM_TYPE_BIT, SFR_TCON_TF0);
        if (tf0)
        {
            enter_interrupt(INT_TIMER0_ENTRY);
            simu8051_write(MEM_TYPE_BIT, SFR_TCON_TF0, 0);
        }
    }
}
void simu8051_exec(instr_t *instr)
{
    instr->info->exec(instr);
    update_psw_p();
#if 1    //表示是否有数据可以去接收
    if (simu8051_uart_rx_rdy())
    {

        simu8051_write(MEM_TYPE_BIT, SFR_SCON_RI, 1);
    }
#endif
    update_timer(instr->info->cycles);    //利用cycles模拟时间
    process_interrupt();                  //处理中断
    /**
     * 用于最初级的形态,建立指令表之后废弃
    switch (instr->opcode)
    {
    case 0x00:
        printf("PC:%d,operation:%s,opcode:%s\n", simu.pc, "nop", u8toBinary(instr->opcode));
        simu.pc += 1;
        simu.cycles += 1;
        break;
    case 0x80:
        printf("PC:%d,operation:%s,opcode:%s\n", simu.pc, "sjmp", u8toBinary(instr->opcode));
        simu.pc += 2 + (int8_t)instr->op0;
        simu.cycles += 2;
        break;
    default:
        printf("PC:%d,operation:%s,opcode:%s\n", simu.pc, "error opcode:", u8toBinary(instr->opcode));
        return;
    }
        */
}

void simu8051_run(uint16_t stop_addr, uint32_t stop_cycle)
{
    printf("begin test program.\n");
    do
    {
        instr_t instr;
        simu8051_fetch_instr(&instr);
        // show_disa(&instr);
        simu8051_exec(&instr);
        // simu8051_dump_regs();
    } while ((!stop_addr || stop_addr != simu8051_pc()) && (!stop_cycle || stop_cycle > simu8051_cycle()));
    printf("end test!\n");
}